package com.lc.command;

import com.lc.protocol.DeviceError;

import org.json.JSONObject;

/**
 * Created by zhyioo on 2017/8/8.
 */

public class TimedCommand implements ICommand {
    /**
     * 设置指定任务为定时任务
     * @param worker 需要设置的命令调度器
     * @param work 需要工作的命令
     * @param timeoutMs 需要设置的超时时间(0则表示一直运行)
     * @param callback 工作命令的回调
     * @param intervalMs 轮询间隔
     * @return 调度的任务对象
     */
    public static TimedCommand AsyncTimeoutMs(CommandDispatcher worker, ICommand work, JSONObject arg, long timeoutMs, ICommand callback, long intervalMs) {
        TimedCommand cmd = new TimedCommand(callback, timeoutMs);
        worker.Background(work, arg, cmd, intervalMs);
        return cmd;
    }

    public static TimedCommand AsyncTimeoutMs(CommandDispatcher worker, ICommand work, JSONObject arg, long timeoutMs, ICommand callback) {
        return AsyncTimeoutMs(worker, work, arg, timeoutMs, callback, 0);
    }

    protected ICommand _callback = null;
    protected long _timeoutMs = 0;
    protected long _tickCount = 0;
    protected boolean _isCancel = false;

    public TimedCommand() {}

    public TimedCommand(ICommand callback, long timeoutMs) {
        Make(callback, timeoutMs);
    }

    public boolean Make(ICommand callback, long timeoutMs) {
        _callback = callback;
        _timeoutMs = timeoutMs;

        _tickCount = System.currentTimeMillis();
        return true;
    }

    public boolean IsTimeout() {
        if(_timeoutMs < 1) {
            return false;
        }
        long currentTime = System.currentTimeMillis();
        return (currentTime - _tickCount) >= _timeoutMs;
    }

    public void Cancel() {
        _isCancel = true;
    }

    /// 返回是否需要设置为后台任务继续执行
    protected boolean TimedWork(JSONObject arg, JSONObject rlt) {
        if(CommandDispatcher.IsTaskOK(arg)) {
            CommandActuator.LogErr(rlt, DeviceError.Success, "");
            return false;
        }
        if(IsTimeout()) {
            CommandActuator.LogErr(rlt, DeviceError.WaitTimeOutErr, "任务超时");
            return false;
        }
        if(_isCancel) {
            CommandActuator.LogErr(rlt, DeviceError.OperatorInterruptErr, "任务被取消");
            return false;
        }
        return true;
    }

    @Override
    public boolean Run(JSONObject arg, JSONObject rlt) {
        boolean isOK = TimedWork(arg, rlt);
        if(!isOK) {
            CommandDispatcher.SetBackground(arg, isOK);
            if(_callback != null) {
                _callback.Run(arg, rlt);
            }
        }
        return true;
    }
}
